﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using System.IO;

namespace YahooMoviesStormer
{
    class Communications
    {
        string UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";

        public ProxyInfo proxyInfo { get; set; }
        public CookieContainer cookieMonster = new CookieContainer();

        public Communications()
        {
            System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
                System.Security.Cryptography.X509Certificates.X509Certificate certificate,
                System.Security.Cryptography.X509Certificates.X509Chain chain,
                System.Net.Security.SslPolicyErrors sslPolicyErrors)
            { return true; };
        }

        public void ClearCookies()
        {
            cookieMonster = new CookieContainer();
        }

        public class ProxyInfo
        {
            public string IP { get; set; }
            public string Port { get; set; }
            public string User { get; set; }
            public string Password { get; set; }

            public override string ToString()
            {
                if (User != null) return string.Join(":", new string[] { IP, Port, User, Password });
                else return string.Join(":", new string[] { IP, Port });
            }
        }

        HttpWebRequest PrepareWebRequest(string url, string referer = "", string accept = "", bool allowAutoRedirect = true)
        {
            var proxyBasicUri = new Uri(url);

            //if (proxyInfo != null && proxyInfo.User != null && proxyInfo.User != "")
            //{
            //    NetworkCredential nc = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
            //    CredentialCache cache = new CredentialCache();
            //    cache.Add(proxyBasicUri, "Basic", nc);
            //}

            var request = HttpWebRequest.Create(proxyBasicUri) as HttpWebRequest;

            if (proxyInfo != null)
            {
                request.Proxy = GetProxy();
                if (proxyInfo.User != null && proxyInfo.User != "")
                {
                    request.Proxy.Credentials = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
                }
            }

            request.AllowAutoRedirect = allowAutoRedirect;
            request.CookieContainer = cookieMonster;
            request.UserAgent = UserAgent;
            request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
            request.Timeout = 60000;
            if (referer != "") request.Referer = referer;
            if (accept != "") request.Accept = accept;

            return request;
        }

        public string PerformGet(string url, string referer = "",string accept = "", bool allowAutoRedirect = false)
        {
            var request = PrepareWebRequest(url, referer, accept, allowAutoRedirect);
            request.Method = "GET";
            return ReadResponseStream(request);
        }

        WebProxy GetProxy()
        {
            if (proxyInfo != null)
            {
                var proxy = new WebProxy(proxyInfo.IP, int.Parse(proxyInfo.Port));
                if (proxyInfo.User != "" && proxyInfo.User != null)
                    proxy.Credentials = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
                return proxy;
            }
            return null;
        }

        public string PerformPost(string url, PostData postData, string referer = "", bool allowAutoRedirect = false)
        {
            try
            {
                var request = PrepareWebRequest(url, referer, allowAutoRedirect: allowAutoRedirect);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";

                byte[] bytes = Encoding.ASCII.GetBytes(postData.ToString());
                request.ContentLength = bytes.Length;

                using (Stream writeStream = request.GetRequestStream())
                {
                    writeStream.Write(bytes, 0, bytes.Length);
                }
                return ReadResponseStream(request);
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    WebResponse resp = e.Response;
                    using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                    {
                        var f = sr.ReadToEnd();
                        return f;
                    }
                }
            }
            catch (Exception ex)
            {
                return null;
            }
            return null;
        }

        string ReadResponseStream(HttpWebRequest request)
        {
            try
            {
                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    response.Cookies = cookieMonster.GetCookies(request.RequestUri);
                    using (Stream responseStream = response.GetResponseStream())
                    {
                        using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
                        {
                            readStream.BaseStream.ReadTimeout = 60000;
                            return readStream.ReadToEnd();
                        }
                    }
                }
            }
            catch (WebException e)
            {
                if (e.Status == WebExceptionStatus.ProtocolError)
                {
                    WebResponse resp = e.Response;
                    using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                    {
                        var f = sr.ReadToEnd();
                        return f;
                    }
                }
            }
            catch (Exception ex)
            {
                return null;
            }
            return null;
        }

        public class PostData
        {
            private Dictionary<string, string> Values = new Dictionary<string, string>();

            public void AddValue(string key, string value)
            {
                Values.Add(key, HttpUtility.UrlEncode(value));
            }

            public override string ToString()
            {
                List<string> values = new List<string>();
                foreach (KeyValuePair<string, string> pair in Values)
                {
                    values.Add(pair.Key + "=" + pair.Value);
                }
                return string.Join("&", values.ToArray());
            }
        }
    }
}
